#ifndef __DICTIONARY_H__
#define __DICTIONARY_H__
#include <map>
#include <algorithm>
#include <string>

#include "NumberAndWord.h"
#include "BaseTypeDefin.h"

using namespace std;

typedef multimap<int, INumberAndWord* > storerDict;
typedef pair<int, INumberAndWord* > pairStorerDict;
typedef storerDict::iterator pStorDictIter;

class Dictionary
{
public:
	Dictionary();
	~Dictionary();
	void	add(INumberAndWord* pNum);

	template<typename T>
	bool searchValue(long pValue, int pRank, typename T* pT)
	{
		if ( !isEmpty() )
		{
			pair<pStorDictIter, pStorDictIter> pResultRank = storer.equal_range(pRank);
			*pT = for_each(pResultRank.first, pResultRank.second, *pT);
			if ( pT->getResult()->getValue() != -1 ) return true;		
		}
		return false;
	};

	template<typename T>
	int countValue(long pValue, int pRank, typename T* pT)
	{
		if ( !isEmpty() )
		{
			pair<pStorDictIter, pStorDictIter> pResultRank = storer.equal_range(pRank);
			return count_if(pResultRank.first, pResultRank.second, *pT);		
		}
		return 0;
	};

	int		countValue(long pValue, int pRank);
	bool	isBaseValue(long pValue);
	bool	isEmpty();
	int		size();

protected:
private:
	storerDict storer;
};

class IAlgorithms
{
public:
	virtual bool operator() (pairStorerDict x) = 0;
};

class ISearchAlgorithms : public IAlgorithms
{
public:
	virtual INumberAndWord* getResult() const = 0;
	virtual ~ISearchAlgorithms(){};
};

class BasicSearch : public ISearchAlgorithms
{
public:
	BasicSearch(long pValue):value( giveNumberWithoutZero( pValue ) ),storer( new myNumberAndWord() ){};

	bool operator() (pairStorerDict x)
	{
		if (x.second->getValue() == value )
		{
			storer = x.second;
			return true;
		}
		return false;
	};
	INumberAndWord* getResult() const
	{
		return storer;
	};
	virtual ~BasicSearch()
	{};
protected:
private:
	INumberAndWord* storer;
	long value;
};

class SearchNonZeroAndBase : public ISearchAlgorithms
{
public:
	SearchNonZeroAndBase(long pValue):value(pValue),storer( new myNumberAndWord() ){};
	bool operator() (pairStorerDict x)
	{
		if ( ( x.second->getValue() == value ) || ( value == 0 && x.second->getType() > 1 ) )
		{
			storer = x.second;
			return true;
		}
		return false;
	};
	INumberAndWord* getResult() const
	{
		return storer;
	};
	virtual ~SearchNonZeroAndBase()
	{};
protected:
private:
	INumberAndWord* storer;
	long value;
};

class isBaseRank : public ISearchAlgorithms
{
public:
	isBaseRank(long pValue):value(pValue),storer( new myNumberAndWord() )
	{};

	bool operator() (pairStorerDict x)
	{
		if ( x.second->getType() == 1 /*&& x.second->getValue() == value*/ )
		{
			storer = x.second;
			return true;
		}
		return false;
	};
	INumberAndWord* getResult() const
	{
		return storer;
	};
	virtual ~isBaseRank(){};
protected:
private:
	INumberAndWord* storer;
	long value;
};

class makeTranslateForValue : public ISearchAlgorithms
{
public:
	makeTranslateForValue(long pValue):value(pValue),maxLangVal(0),storer( new myNumberAndWord() )
	{};
	bool operator() (pairStorerDict x)
	{
		if ( ( x.second->getType() > 1 ) && ( maxLangVal < giveNumberWithoutZero( x.second->getValue() ) && giveNumberWithoutZero ( x.second->getValue() ) < value ) )
		{
			maxLangVal = x.second->getValue();
			storer = x.second;	
			return true;
		}
		return false;
	};
	INumberAndWord* getResult() const
	{
		return storer;
	};

	virtual ~makeTranslateForValue()
	{};
protected:
private:
	INumberAndWord* storer;
	long maxLangVal;
	long value;
};

class countNumberOfVar : public IAlgorithms
{
public:
	countNumberOfVar(long pValue):value(pValue), ready(false){};
	bool operator() (pairStorerDict x)
	{
		string pStr;
		if ( value == 0 && x.second->getType() > 1 && !ready)
		{
			ready = true;
			return true;
		}
		else
		{
			pStr = ToString<int>( x.second->getValue() );
			pStr = pStr[0];
			if ( StringTo<int>( pStr ) == value && !ready)
			{
				return true;
			}
		}
		return false;
	};

	virtual ~countNumberOfVar(){};
protected:
private:
	long value;
	bool ready;
	
};
#endif __DICTIONARY_H__